#ifndef _THREAD_POOL_HPP
#define _THREED_POOL_HPP


#include<iostream>
#include<queue>
#include<pthread.h>
#include"LOG.hpp"
#define NUM 5    //线程池里总共的线程

typedef int(*hander_t)(int) ;1  //函数指针

class Task     //封装任务
{
    private:
        int sock;
        hander_t hander;                   ///处理sock的 方法
    public:
        Task(int sock_, hander_t hander_)
            :sock(sock_)
            ,hander(hander_)   //用函数指针来初始化
            {}
        void Run()
        {
            hander(sock);   //当前有一个处理方法
        }
        ~Task()
        {}


};

class ThreadPool           //线程池
{
    private:
        int thread_toatl_num;   //线程池总程数
        int thread_idle_num;    //休眠（空闲）的线程数
        std::queue<task> task_queue;  //任务队列，为什么要给任务队列，因为比如线程池里最大有5个任务，最大能处理五个，那么当过来十个任务的时候，就要把剩余的任务给放在队列里，是什么任务？服务器交过来的sock，怎么处理sock的hander（谁给任务队列里放任务----服务器，线程从队列拿任务，生产者消费者模型）

        pthread_mutex_t lock;        //用锁来保护临界资源（互斥）
        pthread_cont_t cod;         //条件变量（同步）
        bool is_quit;             //线程退出
   private:
        void LockQueue()
        {
          pthread_mutex_lock(&lock);                                         //把任务锁起来
        }
        void UnlockQueue()
        {
         pthread_mutex_unlocck(&lock);                         //解锁
        }

        bool IsEmpty()   //队列里是否有任务
        {
            return task_routine.size() ==0;
              
        }

        static void * thread_routine(void *arg)  ///线程做的事情，从任务队列里拿队列-----它要访问临界资源，这个函数只能传递一个参数，但是他是成员函数，还会默认一个this参数。所有应该声明为ststic
        {
            ThreadPool * tp = (ThreadPoll)*arg;

            pthread_detach(pthread_self()); //线程为什么要分离 
            for(;;)
            {

            tp-> LockQueue();
             while (tp->IsEmpty()) //当醒了后还有可能没有任务
             {
               Thread_Idle(); //任务队列为空则等待,进入休眠
             }                                                             
             //从queue里面拿去任务
             Task t;
             tp->PopTask(t);
            tp-> UnlockQueue();
             LOG(INFO,"task has been taken,hander.....");
             std::cout<<
             //拿到任务后，开始执行
             t.Run();  //自动处理任务
           }

        }

         void  Thread_Idle()  //进入休眠
         {
             if(is_quit)
             {
                 LOG(INFO,"thread quit！");
                 yhread_total_num--;
                 pthread_exit((void*)0);
             }

             thread_idle_num++;
        //一个线程进入休眠idle后自动释放锁
          pthread_cond_wait(&cond,&lock);
          thread_idle_num--;  //醒来后
       }
                            
    public:
        ThreadPool(int num=NUM)  //构造函数,给线程一个初始值
            :thread_toatl_num(0)   //初始值，一开始是没有的
            ,thread_idle_num(0)
            ,is_quit(false)
        {
                   
          pthread_mutex_init(&lock,NULL);   //干嘛的
          pthread_cond_init(&cond,NULL);

        }
        void InitThreadPool()  //初始化线程池，创建一批线程出来
        {
              int i = 0;`
              for(; i<thread_total_num;i++)
              {
                  pthread_t tid;
                  pthread_creat(&tid,NULL,thread_routine,this);       //创建
              }

        }
        void WakeupAllThread()//唤醒在该条件变量下所有等待的线程，即休眠的线程
        {
            pthread_cond_broadcast(&cond);   //唤醒全部在休眠的接口
                  
        }
        void WakeupOneThread()//唤醒线程
        {
           pthread_cond_signal(&cond);   //在条件变量下唤醒线程                                
        }
        void PushTask(Task &t)  //可以把任务放在队列里面
        {
        
            LockQueue();
            if(is_quit)    //线程池打算退出
            {
                UnlockQueue();
                return ; 
            }
            task.queue.push(t);
            WakeupOneThread(); //把任务放进去后赶紧唤醒，被唤醒后的线程先检测是否有任务
            UnlockQueue();
       }
        void PopTask(Task& t)
        {
            t_ = task_queue.front();
            task_queue.pop();
        }
        void Stop()  //所有线程退出，线程池退出
        {
           LockQueue();
           is_quit = true;  //每个线程都要就检测
           UnlockQueue();
           while(thread_idle_num>0)
           {
              WakeupAllThread();
           }
        }
        
        ~ThreadPool()
        {
          pthread_mutex_destory(&lock,NULL);
          pthread_cond_destory(&cond,NULL);
          
        }




};



#endif
